package com.gs.pdf.to.word.pdf;


import com.gs.pdf.to.word.model.TextChunk;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBorder;

import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

public class StyledDOCXWriter {

    public static void write(List<AdvancedPDFExtractor.ContentItem> content, String outputPath) throws Exception {
        XWPFDocument doc = new XWPFDocument();

        List<AdvancedPDFExtractor.ContentItem> remaining = new ArrayList<>(content);
        List<TableDetector.TableCell> tableCells = TableDetector.detectTable(content);

        if (!tableCells.isEmpty()) {
            createTable(doc, tableCells);
            remaining.removeIf(item -> item.isText() && belongsToTable(item.text, tableCells));
        }

        for (AdvancedPDFExtractor.ContentItem item : remaining) {
            if (item.isText()) {
                XWPFParagraph p = doc.createParagraph();
                formatParagraph(p, item.text);
            } else if (item.isImage()) {
                XWPFParagraph p = doc.createParagraph();
                XWPFRun run = p.createRun();
                run.addPicture(
                    new java.io.ByteArrayInputStream(item.imageBytes),
                    XWPFDocument.PICTURE_TYPE_PNG, "img.png",
                    org.apache.poi.util.Units.toEMU(400),
                    org.apache.poi.util.Units.toEMU(300)
                );
                p.setAlignment(ParagraphAlignment.CENTER);
            }
        }

        try (FileOutputStream out = new FileOutputStream(outputPath)) {
            doc.write(out);
        }
        doc.close();
    }

    private static boolean belongsToTable(TextChunk text, List<TableDetector.TableCell> cells) {
        return cells.stream().anyMatch(c -> c.content.equals(text.text));
    }

    private static void formatParagraph(XWPFParagraph p, TextChunk text) {
        XWPFRun run = p.createRun();
        run.setText(text.text);
        run.setFontSize((int) text.fontSize);
        run.setBold(text.bold);
        run.setItalic(text.italic);
        run.setFontFamily(sanitizeFontName(text.fontName));

        if (text.x < 100) p.setAlignment(ParagraphAlignment.LEFT);
        else if (text.x > 400) p.setAlignment(ParagraphAlignment.RIGHT);
        else p.setAlignment(ParagraphAlignment.CENTER);
    }

    private static String sanitizeFontName(String name) {
        return name.replaceAll(".*?\\+", "").split("-")[0];
    }

    private static void createTable(XWPFDocument doc, List<TableDetector.TableCell> cells) {
        int maxRow = cells.stream().mapToInt(c -> c.row).max().orElse(0) + 1;
        int maxCol = cells.stream().mapToInt(c -> c.col).max().orElse(0) + 1;

        XWPFTable table = doc.createTable(maxRow, maxCol);
        table.setWidth("100%");

        for (TableDetector.TableCell cell : cells) {
            if (cell.row < maxRow && cell.col < maxCol) {
                XWPFTableCell cellObj = table.getRow(cell.row).getCell(cell.col);
                cellObj.setText(cell.content);
            }
        }

        org.apache.xmlbeans.XmlCursor cursor = table.getCTTbl().newCursor();
        cursor.toNextToken();
        org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr tblPr = table.getCTTbl().getTblPr();
        if (tblPr == null) tblPr = table.getCTTbl().addNewTblPr();
        CTBorder border = tblPr.addNewTblBorders().addNewInsideH();
        border.setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder.SINGLE);
    }
}